package com.frost.system.service.exam.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.frost.common.core.enums.ResultCode;
import com.frost.common.security.exception.ServiceException;
import com.frost.system.domain.exam.Exam;
import com.frost.system.domain.exam.ExamQuestion;
import com.frost.system.domain.exam.dto.ExamAddDTO;
import com.frost.system.domain.exam.dto.ExamQueryDTO;
import com.frost.system.domain.exam.dto.ExamQuestionAddDTO;
import com.frost.system.domain.exam.vo.ExamDetailVO;
import com.frost.system.domain.exam.vo.ExamVO;
import com.frost.system.domain.question.Question;
import com.frost.system.domain.question.vo.QuestionVO;
import com.frost.system.mapper.exam.ExamMapper;
import com.frost.system.mapper.exam.ExamQuestionMapper;
import com.frost.system.mapper.question.QuestionMapper;
import com.frost.system.service.exam.IExamService;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class ExamServiceImpl extends ServiceImpl<ExamQuestionMapper, ExamQuestion> implements IExamService {

    @Autowired
    private ExamMapper examMapper;

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private ExamQuestionMapper examQuestionMapper;

    @Override
    public List<ExamVO> list(ExamQueryDTO examQueryDTO) {
        PageHelper.startPage(examQueryDTO.getPageNum(), examQueryDTO.getPageSize());
        List<ExamVO> examVOList = examMapper.selectExamList(examQueryDTO);// 分页数据,对应页码下的分页数据列表
        return examVOList;
    }

    @Override
    public String add(ExamAddDTO examAddDTO) {
        // 判断竞赛(根据标题)的重复性,查询已有该题目抛异常
        List<Exam> examList = examMapper.selectList(new LambdaQueryWrapper<Exam>()
                .eq(Exam::getTitle, examAddDTO.getTitle()));
        if (CollectionUtil.isNotEmpty(examList)) {
            throw new ServiceException(ResultCode.FAILED_ALREADY_EXISTS);
        }

        if (examAddDTO.getStartTime().isBefore(LocalDateTime.now())) {
            throw new ServiceException(ResultCode.EXAM_START_TIME_BEFORE_CURRENT_TIME);
        }
        if (examAddDTO.getStartTime().isAfter(examAddDTO.getEndTime())) {
            throw new ServiceException(ResultCode.EXAM_START_TIME_AFTER_END_TIME);
        }

        Exam exam = new Exam();
        BeanUtil.copyProperties(examAddDTO, exam);
        examMapper.insert(exam);
        return exam.getExamId().toString();
    }

    @Override
    public boolean questionAdd(ExamQuestionAddDTO examQuestionAddDTO) {
        Exam exam = getExam(examQuestionAddDTO.getExamId());
        Set<Long> questionIdSet = examQuestionAddDTO.getQuestionIdSet();
        if (CollectionUtil.isEmpty(questionIdSet)) {
            return true;
        }

        List<Question> questionList = questionMapper.selectBatchIds(questionIdSet);
        if (CollectionUtil.isEmpty(questionList) || questionList.size() < questionIdSet.size()) {
            throw new ServiceException(ResultCode.EXAM_QUESTION_NOT_EXISTS);
        }

        return saveExamQuestion(exam, questionIdSet);
    }

    @Override
    public ExamDetailVO detail(Long examId) {
        ExamDetailVO examDetailVO = new ExamDetailVO();
        Exam exam = getExam(examId);
        BeanUtil.copyProperties(exam, examDetailVO);
        List<ExamQuestion> examQuestionList = examQuestionMapper.selectList(new LambdaQueryWrapper<ExamQuestion>()
                .select(ExamQuestion::getQuestionId)
                .eq(ExamQuestion::getExamId, examId)
                .orderByDesc(ExamQuestion::getQuestionOrder));
        if (CollectionUtil.isEmpty(examQuestionList)) {
            // 返回详情，只包含竞赛的基本信息，不包含题目
            return examDetailVO;
        }
        List<Long> questionIdList = examQuestionList.stream().map(ExamQuestion::getQuestionId).toList();
        // select question_id,title,difficulty from tb_question question_id in (1, 2, 3);
        List<Question> questionList = questionMapper.selectList(new LambdaQueryWrapper<Question>()
                .select(Question::getQuestionId, Question::getTitle, Question::getDifficulty)
                .in(Question::getQuestionId, questionIdList));

        List<QuestionVO> questionVOList = BeanUtil.copyToList(questionList, QuestionVO.class);
        examDetailVO.setExamQuestionList(questionVOList);
        return examDetailVO;
    }

    private Exam getExam(Long examId) {
        Exam exam = examMapper.selectById(examId);
        if (exam == null) {
            throw new ServiceException(ResultCode.EXAM_NOT_EXISTS);
        }
        return exam;
    }

    /**
     * 将question存储到exam中
     * @param exam
     * @param questionIdSet
     * @return
     */
    private boolean saveExamQuestion(Exam exam, Set<Long> questionIdSet) {
        int num = 1;
        List<ExamQuestion> examQuestionList = new ArrayList<>();
        for (Long questionId : questionIdSet) {
            ExamQuestion examQuestion = new ExamQuestion();
            examQuestion.setExamId(exam.getExamId());
            examQuestion.setQuestionId(questionId);
            examQuestion.setQuestionOrder(num++);
            examQuestionList.add(examQuestion);
        }
        return saveBatch(examQuestionList);

        // 上述代码是对以下代码的优化，以下代码操作数据库太过于频繁，大量减少多次操作数据库的次数
//        for (Long questionId : questionIdSet) {
//            //判断question是否为空
//            Question question = questionMapper.selectById(questionId);
//            if (question == null) {
//                throw new ServiceException(ResultCode.EXAM_QUESTION_NOT_EXISTS);
//            }
//            ExamQuestion examQuestion = new ExamQuestion();
//            examQuestion.setExamId(exam.getExamId());
//            examQuestion.setQuestionId(questionId);
//            examQuestion.setQuestionOrder(num++);
//            examQuestionMapper.insert(examQuestion);
//        }
    }


}
